<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Ghidra Debugger</title>
  <style>
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type="checkbox"] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style>
  <link rel="stylesheet" href="style.css" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="nav"><a
 class="beginner" href="A1-GettingStarted.html">Getting Started</a><a
 class="beginner" href="A2-UITour.html">UI Tour</a><a
 class="beginner" href="A3-Breakpoints.html">Breakpoints</a><a
 class="beginner" href="A4-MachineState.html">Machine State</a><a
 class="beginner" href="A5-Navigation.html">Navigation</a><a
 class="beginner" href="A6-MemoryMap.html">Memory Map</a><a
 class="advanced" href="B1-RemoteTargets.html">Remote Targets</a><a
 class="advanced" href="B2-Emulation.html">Emulation</a><a
 class="advanced" href="B3-Scripting.html">Scripting</a><a
 class="advanced" href="B4-Modeling.html">Modeling</a><a
 class="advanced" href="B5-AddingDebuggers.html">Adding Debuggers</a>
</header>
<header id="title-block-header">
<h1 class="title">Ghidra Debugger</h1>
</header>
<nav id="TOC" role="doc-toc">
<ul>
<li><a href="#remote-targets" id="toc-remote-targets">Remote Targets</a>
<ul>
<li><a href="#module-mapping-caveats"
id="toc-module-mapping-caveats">Module Mapping Caveats</a></li>
<li><a href="#variation-in-configuration"
id="toc-variation-in-configuration">Variation in Configuration</a></li>
<li><a href="#using-gdbserver-over-ssh"
id="toc-using-gdbserver-over-ssh">Using <code>gdbserver</code> over
SSH</a></li>
<li><a href="#using-trace-rmi-over-ssh"
id="toc-using-trace-rmi-over-ssh">Using Trace RMI over SSH</a>
<ul>
<li><a href="#troubleshooting"
id="toc-troubleshooting">Troubleshooting</a></li>
</ul></li>
<li><a href="#using-gdbserver-manually"
id="toc-using-gdbserver-manually">Using <code>gdbserver</code>
manually</a></li>
<li><a href="#connecting-trace-rmi-manually"
id="toc-connecting-trace-rmi-manually">Connecting Trace RMI
manually</a></li>
<li><a href="#rube-goldberg-configurations"
id="toc-rube-goldberg-configurations">Rube Goldberg
Configurations</a></li>
<li><a href="#exercise-debug-your-friends-termmines"
id="toc-exercise-debug-your-friends-termmines">Exercise: Debug your
Friend’s <code>termmines</code></a></li>
</ul></li>
</ul>
</nav>
<section id="remote-targets" class="level1">
<h1>Remote Targets</h1>
<p>This is the first module of the Advanced part of this course. It
assumes you have completed the Beginner portion. At the very least, you
should complete <a href="A1-GettingStarted.html">Getting Started</a> and
<a href="A2-UITour.html">A Tour of the Debugger UI</a> first.</p>
<section id="module-mapping-caveats" class="level2">
<h2>Module Mapping Caveats</h2>
<p>Beware! Many of the conveniences in Ghidra assume that the target is
running from the same file system as Ghidra, which will not be the case
when the target is remote. Be sure your current project is populated
only with programs imported from the target’s file system. Additionally,
if prompted to import something new, be sure to redirect to the remote
file system, because the dialog will default to the path on the local
file system.</p>
</section>
<section id="variation-in-configuration" class="level2">
<h2>Variation in Configuration</h2>
<p>There are a number of configurations for remote debugging with many
moving parts. Some of those parts are contributed by Ghidra’s Debugger,
some are not. Depending on your particular target and platform, there
may be several options available to you. Consider a remote Linux target
in user space. While this list is not exhaustive, some options are:</p>
<ul>
<li>Use <code>gdbserver</code> over SSH</li>
<li>Use Trace RMI over SSH</li>
<li>Use <code>gdbserver</code> and connect to it manually</li>
<li>Connect Trace RMI manually</li>
</ul>
<p>Generally, for each of these options it boils down to which
components will be colocated with the target and which will be colocated
with Ghidra.</p>
</section>
<section id="using-gdbserver-over-ssh" class="level2">
<h2>Using <code>gdbserver</code> over SSH</h2>
<p>In this configuration, Ghidra and GDB will be located in the user’s
local environment, while <code>gdbserver</code> and the specimen will be
located in the target environment. We will connect the local
<code>gdb</code> to the remote <code>gdbserver</code> by forwarding
stdio over SSH.</p>
<ol type="1">
<li><p>First, prepare the target, which for demonstration purposes has
the IP address 10.0.0.1. Generally, this just means booting it up and
ensuring it has <code>gdbserver</code> installed. <strong>NOTE</strong>:
You do not need to run <code>gdbserver</code> or the target binary. The
launcher will do that for you.</p></li>
<li><p>From the launch menu, select <strong>gdb + gdbserver via
ssh</strong>.</p>
<figure>
<img src="images/RemoteTargets_GdbPlusGdbserverViaSsh.png"
alt="Connect dialog for gdb + gdbserver via ssh" />
<figcaption aria-hidden="true">Connect dialog for gdb + gdbserver via
ssh</figcaption>
</figure></li>
<li><p>Read the wall of text, at least the first time, and verify the
remote system is prepared.</p></li>
<li><p>Fill out the options appropriately. Notably, correct the location
of the target image to point at its location on the <em>target</em>
system. Enter “user@10.0.0.1” for the <strong>[User@]Host</strong>
option, substituting your username for the remote system.</p></li>
<li><p>Click <strong>Launch</strong>.</p></li>
</ol>
<p>At this point, most things will work the same as they would for a
local target.</p>
</section>
<section id="using-trace-rmi-over-ssh" class="level2">
<h2>Using Trace RMI over SSH</h2>
<p>In this configuration, Ghidra will be located in the user’ls local
environment, while <code>gdb</code> and the specimen will be located in
the target environment. Notice that we are <em>not</em> using
<code>gdbserver</code>. We will connect the local Ghidra to the remote
<code>gdb</code> by forwarding Trace RMI over SSH. See the help (press
<strong><code>F1</code></strong> on the <strong>gdb via ssh</strong>
menu item for advantages and disadvantages of using this
vs. <code>gdbserver</code>.)</p>
<ol type="1">
<li><p>First, prepare the target. This is more involved than using
<code>gdbserver</code>, since you will need to ensure <code>gdb</code>
and the Trace RMI plugin for it are installed. The packages, which
should be included with Ghidra, are <code>ghidratrace</code> and
<code>ghidragdb</code>, but you may need to build them first. If you
installed <code>gdb</code> and <code>python3</code> from your
distribution’s repositories, installation of the Python packages should
be straightfoward. Search the Ghidra installation for files ending in
<code>.whl</code>. If the <code>ghidratrace</code> and
<code>ghidragdb</code> packages are there, you can skip this build step
and just transfer them to the target. On the local system:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">-m</span> pip install build <span class="co"># unless you already have it</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> /path/to/ghidra/Ghidra/Debug/Debugger-rmi-trace/pypkg</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">-m</span> build</span></code></pre></div>
<p>This will output <code>.tar.gz</code> and <code>.whl</code> files
under <code>pypkg/dist</code>. Do the same for
<code>Debugger-agent-gdb/pypkg</code>. Transfer the resulting
<code>.whl</code> files to the target, then on the target system:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">-m</span> pip install /path/to/ghidratrace-<span class="pp">[</span><span class="ss">version</span><span class="pp">]</span>.whl /path/to/ghidragdb-<span class="pp">[</span><span class="ss">version</span><span class="pp">]</span>.whl</span></code></pre></div>
<p>If you are offline, the dependencies are included in the
<code>pypkg/dist</code> directory for each module. Transfer and install
them, too. You may try
<code>python -m pip install --no-index -f /path/to/packages ghidragdb</code>,
if all the packages and dependencies are in the one directory. Chances
are, GDB embeds the same Python, so they become importable from GDB.
Test using <code>gdb</code> on the target system:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode gdb"><code class="sourceCode gdbsyntax"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>python import ghidragdb</span></code></pre></div>
<p>No news is good news! You can quit GDB, since that was just for
verifying the installation.</p></li>
<li><p>From the launch menu, select <strong>gdb via ssh</strong>.</p>
<figure>
<img src="images/RemoteTargets_GdbViaSsh.png"
alt="Connect dialog for gdb via SSH" />
<figcaption aria-hidden="true">Connect dialog for gdb via
SSH</figcaption>
</figure></li>
<li><p>Fill out the options appropriately. Notably, correct the location
of the target image to point at its location on the <em>target</em>
system. Enter “user@10.0.0.1” for the <strong>[User@]Host</strong>
option, substituting your username for the remote system.</p></li>
<li><p>Click <strong>Launch</strong>.</p></li>
</ol>
<p>At this point, most things will work the same as they would for a
local target.</p>
<section id="troubleshooting" class="level3">
<h3>Troubleshooting</h3>
<section id="i-cant-find-the-python-packages-to-install" class="level4">
<h4>I can’t find the Python packages to install</h4>
<p>You may need to build them using the instructions above. The
dependencies are included in the Ghidra installation, but perhaps
something has gone missing. Search for files ending in <code>.whl</code>
or <code>.tar.gz</code>; they should be located in
<code>pypkg/dist</code> in various modules. If you are able to do local
debugging with Ghidra and <code>gdb</code>, then the source is
definitely present and functioning. To (re-)build the packages from
source:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">-m</span> pip install build</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> /path/to/ghidra/Ghidra/Debug/Debugger-rmi-trace/pypkg</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">python3</span> <span class="at">-m</span> build</span></code></pre></div>
<p>This should output a <code>.tar.gz</code> and a <code>.whl</code>
file under <code>pypkg/dist</code>. Send the <code>.whl</code> over to
the target system and <code>pip install</code> it. Do the same for
Debugger-agent-gdb. If that doesn’t work, then in the worst case, copy
the Python source over and add it to your <code>PYTHONPATH</code>.</p>
</section>
<section id="the-python-import-ghidragdb-command-fails" class="level4">
<h4>The <code>python import ghidragdb</code> command fails</h4>
<p>Double-check that you have installed all the required packages and
their dependencies. A common forgotten or incorrectly-versioned
dependency is <code>protobuf</code>. We developed using
<code>protobuf==3.20.3</code>. Its “sdist” package is distributed with
Ghidra under <code>Debugger-rmi-trace/pypkg/dist</code> for your
convenience.</p>
<p>It is also possible that <code>gdb</code> has embedded a different
version of the interpreter than the one that <code>python3</code>
provides. This can happen if you built GDB or Python yourself, or you
installed them from a non-standard repository. Check the actual path of
the Python library used by <code>gdb</code>:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ldd</span> <span class="va">$(</span><span class="fu">which</span> gdb<span class="va">)</span></span></code></pre></div>
<p>Or, inside <code>gdb</code>:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode gdb"><code class="sourceCode gdbsyntax"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>(gdb) python-interactive</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>&gt;&gt;&gt; import sys</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>&gt;&gt;&gt; sys.version</span></code></pre></div>
<p>Suppose this identifies version 3.9. Retry the installation commands
using <code>python3.9 -m pip ...</code>. If you have multiple copies of
the same version in different locations, you may need to invoke
<code>python3</code> using its complete path.</p>
<p>In the worst case, copy the Python source over and add it to your
<code>PYTHONPATH</code>.</p>
</section>
</section>
</section>
<section id="using-gdbserver-manually" class="level2">
<h2>Using <code>gdbserver</code> manually</h2>
<p>The configuration and result here are similar using
<code>gdbserver</code> over SSH, but will be performed manually.</p>
<ol type="1">
<li><p>First, prepare the target. This time, you will need to start
<code>gdbserver</code> on the remote system manually. For demonstration,
we will listen on 10.0.0.1 port 12345:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">gdbserver</span> 10.0.0.1:12345 termmines</span></code></pre></div></li>
<li><p>From the launch menu, select <strong>remote
gdb</strong>.</p></li>
<li><p>Fill out the options appropriately. Notably, enter “10.0.0.1” for
the <strong>Host</strong> option, and “12345” for the
<strong>Port</strong> option.</p></li>
<li><p>Click <strong>Launch</strong>.</p></li>
</ol>
<p>At this point, most things will work the same as they would for a
local target.</p>
</section>
<section id="connecting-trace-rmi-manually" class="level2">
<h2>Connecting Trace RMI manually</h2>
<p>The configuration and result here are similar to using Trace RMI over
SSH, but will be performed manually.</p>
<ol type="1">
<li><p>First, prepare the target. Follow the same installation steps as
above for Trace RMI over SSH, if you have not already.</p></li>
<li><p>In Ghidra’s Connections window, click <strong>Accept a single
inbound TCP connection</strong> in the local toolbar.</p>
<figure>
<img src="images/RemoteTargets_AcceptTraceRmi.png"
alt="TraceRMI Accept Dialog" />
<figcaption aria-hidden="true">TraceRMI Accept Dialog</figcaption>
</figure></li>
<li><p>Set <strong>Host/Address</strong> to “10.0.0.1”, so that we can
connect to it over the network. <strong>NOTE</strong>: You may leave the
port as “0” or pick a specific port, assuming you have permission to use
it.</p></li>
<li><p>Click <strong>Listen</strong>, and then take note of the
acceptor’s port number in the Connections window, e.g.,
“12345.”</p></li>
<li><p>Now, on the remote system, start <code>gdb</code> and type:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode gdb"><code class="sourceCode gdbsyntax"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>python import ghidragdb</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>file termmines</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a># set args, if you&#39;d like</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>ghidra trace connect 10.0.0.1:12345</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>ghidra trace start</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>ghidra trace sync-enable</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>starti</span></code></pre></div></li>
</ol>
<p>At this point, most things will work the same as they would for a
local target. You may notice Ghidra has not given you a new terminal.
Just use the one you already have on the remote target.</p>
<p>A notable advantage of this configuration is that you can enter
whatever <code>gdb</code> commands you want to start your target. Here
we demonstrated the simplest case of a “native” target. It is also
possible to use this procedure to connect Ghidra into a running
<code>gdb</code> session.</p>
</section>
<section id="rube-goldberg-configurations" class="level2">
<h2>Rube Goldberg Configurations</h2>
<p>While you should always prefer the simpler configuration, it is
possible to combine components to meet a variety of needs. For example,
to debug a native Android target from Windows, you could run Ghidra on
Windows, connect it to GDB via SSH to a Linux virtual machine, e.g.,
WSL2, and then connect that to <code>gdbserver</code> running in an
Android emulator.</p>
</section>
<section id="exercise-debug-your-friends-termmines" class="level2">
<h2>Exercise: Debug your Friend’s <code>termmines</code></h2>
<p>If you are in a classroom setting, pair up. Otherwise, play both
roles, preferably using separate machines for Ghidra and the target.
Using one of the above procedures, debug <code>termmines</code>. One of
you should prepare the target environment. The other should connect to
it and launch the specimen. Then trade roles, choose a different
procedure, and do it again.</p>
</section>
</section>
</body>
</html>
